﻿using System;
using System.IO;
using ITU.MDD.CPML;
using ITU.MDD.UPML;
using Microsoft.VisualStudio.Modeling;

namespace MDD.PML.Utility
{
    /// <summary>
    /// This class is used to create an M2M transforming the PIMs to the PSM
    /// </summary>
    internal class PIM2PSM
    {
        private static Store pimstore = null;
        private static Store psmstore = null;
        private static PageModelPackage pim = null;
        private static DocumentTypePackage psm = null;

        /// <summary>
        /// Deserializes the PIM file
        /// </summary>
        /// <param name="modelPath">The path to the PIM file</param>
        internal static void Transform(string modelPath, ModelType modelType)
        {
            pimstore = new Store(typeof(CPMLDomainModel));

            using (Transaction trans = pimstore.TransactionManager.BeginTransaction("Load PIM"))
            {
                pim = CPMLSerializationHelper.Instance.LoadModel(pimstore, @modelPath, null, null, null);
                // TODO:
                if (modelType == ModelType.all)
                    CreateAll();
                //if (modelType == ModelType.upml)
                //    CreateSPML();
                if (modelType == ModelType.upml)
                    CreateUPML();
            }
        }

        private static void CreateAll()
        {
            // CreateSPML();
            CreateUPML();
        }

        /// <summary>
        /// Create the PSM from the PIM
        /// </summary>
        private static void CreateUPML()
        {
            psmstore = new Store(typeof(UPMLDomainModel));

            using (Transaction trans = psmstore.TransactionManager.BeginTransaction("Create Umbraco PSM from PIM"))
            {
                psm = new DocumentTypePackage(psmstore);
                if (pim.PageModels.Count > 0)
                {
                    foreach (PageModel parent in pim.PageModels)
                    {
                        if (parent.Parent.Count == 0)
                        {
                            DocumentType documenttype = new DocumentType(psmstore)
                            {
                                Name = parent.DisplayName,
                                Alias = parent.InternalName,
                                Description = parent.Description,
                            };

                            if (parent.Attributes.Count > 0)
                            {
                                foreach (CPMLAttribute attribute in parent.Attributes)
                                {
                                    GenericProperty prop = new GenericProperty(psmstore)
                                    {
                                        Name = attribute.DisplayName,
                                        Alias = attribute.InternalName,
                                        Description = attribute.Description,
                                        Mandatory = attribute.Required,
                                        PropertyType = CreateType(attribute.Type)
                                    };

                                    documenttype.GenericProperties.Add(prop);
                                    psm.GenericProperties.Add(prop);
                                }
                            }

                            psm.DocumentTypes.Add(documenttype);

                            if (parent.Children.Count > 0)
                            {
                                foreach (PageModel child in parent.Children)
                                {
                                    CreateChildPageModel(child, documenttype);
                                }
                            }
                        }
                    }

                    try
                    {
                        SerializationResult result = new SerializationResult();

                        Char separator = '_';
                        string fileName = string.Format("{0}.upml", DateTime.Now.ToString().Replace('/', separator).Replace(' ', separator).Replace(':', separator));
                        string filePath = Path.Combine(Directory.GetCurrentDirectory(), fileName);
                        UPMLSerializationHelper.Instance.SaveModel(result, psm, filePath);

                        if (result.Failed)
                        {
                            foreach (SerializationMessage message in result)
                            {
                                Console.WriteLine(message);
                            }
                        }
                    }
                    catch (IOException ex)
                    {
                        throw ex;
                    }
                }
            }
        }

        private static void CreateChildPageModel(PageModel child, DocumentType pagemodel)
        {
            DocumentType documenttypechild = new DocumentType(psmstore)
            {
                Name = child.DisplayName,
                Alias = child.InternalName,
                Description = child.Description,
            };

            if (child.Attributes.Count > 0)
            {
                foreach (CPMLAttribute attribute in child.Attributes)
                {
                    GenericProperty prop = new GenericProperty(psmstore)
                    {
                        Name = attribute.DisplayName,
                        Alias = attribute.InternalName,
                        Description = attribute.Description,
                        Mandatory = attribute.Required,
                        PropertyType = CreateType(attribute.Type)
                    };

                    documenttypechild.GenericProperties.Add(prop);
                    psm.GenericProperties.Add(prop);
                }
            }

            pagemodel.Children.Add(documenttypechild);
            psm.DocumentTypes.Add(documenttypechild);

            if (pagemodel.Children.Count > 0)
            {
                foreach (PageModel grandchild in child.Children)
                {
                    CreateChildPageModel(grandchild, documenttypechild);
                }
            }
        }

        private static GenericPropertyType CreateType(AttributeType attributeType)
        {
            switch (attributeType)
            {
                case AttributeType.Boolean:
                    return GenericPropertyType.Boolean;

                case AttributeType.CheckBoxes:
                    return GenericPropertyType.CheckboxList;

                case AttributeType.Date:
                    return GenericPropertyType.DatePicker;

                case AttributeType.DateTime:
                    return GenericPropertyType.DatePickerWithTime;

                case AttributeType.DropdownMultipleChoice:
                    return GenericPropertyType.DropdownMultiple;

                case AttributeType.DropdownSingleChoice:
                    return GenericPropertyType.DropDown;

                case AttributeType.HTMLEditorRich:
                    return GenericPropertyType.RichTextEditor;

                case AttributeType.HTMLEditorSimple:
                    return GenericPropertyType.SimpleEditor;

                case AttributeType.Image:
                    return GenericPropertyType.MediaPicker;

                case AttributeType.Number:
                    return GenericPropertyType.Numeric;

                case AttributeType.RadioButtons:
                    return GenericPropertyType.Radiobox;

                case AttributeType.TextBox:
                    return GenericPropertyType.TextboxMultiple;

                case AttributeType.TextLine:
                    return GenericPropertyType.TextString;

                default:
                    throw new Exception("Attribute mapping error");
            }
        }

        internal static void Umbraco2Psm()
        {
            throw new NotImplementedException();
        }
    }
}